module nehe.Lesson03;

import nehe.Lesson;
import nehe.Window;
import nehe.Vertex;

import derelict.opengl.gl;

import tango.util.collection.ArraySeq;

void main()
{
	//Create a scoped lesson instance
	scope Lesson lesson = new Lesson03();

	lesson.init();

	lesson.run();
}

public class Lesson03 : Lesson
{
	private ArraySeq!(Vertex) vertices;
	private ArraySeq!(Vertex) colors;
	// used to store the angle at which we're rotating at the moment
	private float rotationAngle = 0.0f; 
	
	public this()
	{
		vertices = new ArraySeq!(Vertex);
		colors = new ArraySeq!(Vertex);
	}
	
	public override void init()
	{
		window.create(800, 600, 32, "Ne(w)He Lesson 3 - A rotating cube");

		glShadeModel(GL_SMOOTH);		// Enable Smooth Shading
		glClearColor(0.0f, 0.0f, 0.0f, 0.5f);	// Black Background
		glClearDepth(1.0f);			// Depth Buffer Setup
		glEnable(GL_DEPTH_TEST);		// Enables Depth Testing
		glDepthFunc(GL_LEQUAL);			// The Type Of Depth Testing To Do

		//Create a cube inside our vertex buffer
		vertices.append(Vertex(-1.0f, -1.0f,  1.0f ));//Vertex
		colors.append(Vertex(1.0, 0.0, 0.0));//Color
		vertices.append(Vertex( 1.0f, -1.0f,  1.0f ));
		colors.append(Vertex(1.0, 0.0, 0.0));
		vertices.append(Vertex( 1.0f,  1.0f,  1.0f ));
		colors.append(Vertex(1.0, 0.0, 0.0));
		vertices.append(Vertex(-1.0f,  1.0f,  1.0f ));
		colors.append(Vertex(1.0, 0.0, 0.0));

		vertices.append(Vertex(-1.0f, -1.0f, -1.0f ));
		colors.append(Vertex(1.0, 1.0, 0.0));
		vertices.append(Vertex(-1.0f,  1.0f, -1.0f ));
		colors.append(Vertex(1.0, 1.0, 0.0));
		vertices.append(Vertex( 1.0f,  1.0f, -1.0f ));
		colors.append(Vertex(1.0, 1.0, 0.0));
		vertices.append(Vertex( 1.0f, -1.0f, -1.0f ));
		colors.append(Vertex(1.0, 1.0, 0.0));

		vertices.append(Vertex(-1.0f,  1.0f, -1.0f ));
		colors.append(Vertex(1.0, 1.0, 1.0));
		vertices.append(Vertex(-1.0f,  1.0f,  1.0f ));
		colors.append(Vertex(1.0, 1.0, 1.0));
		vertices.append(Vertex( 1.0f,  1.0f,  1.0f ));
		colors.append(Vertex(1.0, 1.0, 1.0));
		vertices.append(Vertex( 1.0f,  1.0f, -1.0f ));
		colors.append(Vertex(1.0, 1.0, 1.0));

		vertices.append(Vertex(-1.0f, -1.0f, -1.0f ));
		colors.append(Vertex(0.0, 1.0, 1.0));
		vertices.append(Vertex( 1.0f, -1.0f, -1.0f ));
		colors.append(Vertex(0.0, 1.0, 1.0));
		vertices.append(Vertex( 1.0f, -1.0f,  1.0f ));
		colors.append(Vertex(0.0, 1.0, 1.0));
		vertices.append(Vertex(-1.0f, -1.0f,  1.0f ));
		colors.append(Vertex(0.0, 1.0, 1.0));

		vertices.append(Vertex( 1.0f, -1.0f, -1.0f ));
		colors.append(Vertex(0.0, 1.0, 0.0));
		vertices.append(Vertex( 1.0f,  1.0f, -1.0f ));
		colors.append(Vertex(0.0, 1.0, 0.0));
		vertices.append(Vertex( 1.0f,  1.0f,  1.0f ));
		colors.append(Vertex(0.0, 1.0, 0.0));
		vertices.append(Vertex( 1.0f, -1.0f,  1.0f ));
		colors.append(Vertex(0.0, 1.0, 0.0));

		vertices.append(Vertex(-1.0f, -1.0f, -1.0f ));
		colors.append(Vertex(0.0, 0.0, 1.0));
		vertices.append(Vertex(-1.0f, -1.0f,  1.0f ));
		colors.append(Vertex(0.0, 0.0, 1.0));
		vertices.append(Vertex(-1.0f,  1.0f,  1.0f ));
		colors.append(Vertex(0.0, 0.0, 1.0));
		vertices.append(Vertex(-1.0f,  1.0f, -1.0f ));
		colors.append(Vertex(0.0, 0.0, 1.0));
	}

	protected override void draw()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
		glLoadIdentity();					// Reset The Current Modelview Matrix
		glTranslatef(0.0f, 0.0f, -8.0f);				// Move everything 8 units into the screen

		// We rotate the cube around the y axis at an angle of "rot",
		// the x-axis of 0.2*rot and z 0.4*rot so we might see each of its sides some time..
		glRotatef(rotationAngle, 0.2, 1.0, 0.4);

		rotationAngle += 0.03; //increase the angle so the cube keeps spinning

		if(rotationAngle > 360.0) //prevent from having an angle greater than a float value can store ^^
		{
			rotationAngle -= 360.0;
		}

		//Now we need to tell OpenGL to use the arrays we filled with data
		glEnableClientState(GL_VERTEX_ARRAY);   //We want a vertex array
		glEnableClientState(GL_COLOR_ARRAY);    //and a color array
		// All values are grouped to three Floats, we start at the beginning of the array (offset=0) and want to use 
		// vertices as VertexArray
		glVertexPointer(3, GL_FLOAT, 0, &vertices.toArray()[0]);   
		glColorPointer(3, GL_FLOAT, 0, &colors.toArray()[0]);      //Same here, but use colors

		// The cube consists only of quads, and we have nothing else in 
		// our array so we draw all vertices
		glDrawArrays(GL_QUADS, 0, vertices.size()); 

		//Disable using the Vertex and Color array
		glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);
	}
}
